SPB Git
2.7 KB · 32 lines typescript
1import { z } from "zod";2import { handler, parseBody, uuid } from "@/lib/api";3import { getPage, updatePage, softDeletePage, restorePage, purgePage, breadcrumb, backlinks, touchOpened, duplicatePage } from "@/lib/pages/service";4import { audit } from "@/lib/audit";56export const GET = handler(async ({ ws, params, req }) => {7  const id = uuid.parse(params.id); const p = await getPage(ws.id, id, { includeDeleted: true });8  if (new URL(req.url).searchParams.get("open") === "1") touchOpened(id).catch(() => {});9  const [crumbs, back] = await Promise.all([breadcrumb(ws.id, id), backlinks(ws.id, id)]);10  return Response.json({ ...p, breadcrumb: crumbs, backlinks: back });11});12export const PATCH = handler(async ({ req, ws, params, user }) => {13  const id = uuid.parse(params.id);14  const b = await parseBody(req, z.object({ title: z.string().max(500).optional(), content: z.any().optional(), icon: z.string().max(16).nullable().optional(), cover: z.string().max(2000).nullable().optional(), properties: z.record(z.string(), z.unknown()).optional(), parentId: z.string().uuid().nullable().optional(), section: z.string().optional(), position: z.number().optional(), pinned: z.boolean().optional(), archived: z.boolean().optional(), type: z.string().optional(), versionReason: z.string().max(100).optional() }));15  const { versionReason, ...patch } = b;16  const p = await updatePage(ws.id, id, patch, { versionReason });17  if (patch.content === undefined) await audit(user.id, "page.update", { type: "page", id }, { keys: Object.keys(patch) });18  return Response.json({ id: p.id, version: p.version, updatedAt: p.updatedAt, title: p.title, wordCount: p.wordCount });19});20export const DELETE = handler(async ({ ws, params, user, req }) => {21  const id = uuid.parse(params.id); const purge = new URL(req.url).searchParams.get("purge") === "1";22  if (purge) { await purgePage(ws.id, id); await audit(user.id, "page.purge", { type: "page", id }); return Response.json({ ok: true }); }23  const n = await softDeletePage(ws.id, id); await audit(user.id, "page.trash", { type: "page", id }, { count: n });24  return Response.json({ ok: true, trashed: n });25});26export const POST = handler(async ({ ws, params, user, req }) => {27  const id = uuid.parse(params.id); const action = new URL(req.url).searchParams.get("action");28  if (action === "restore") { await restorePage(ws.id, id); await audit(user.id, "page.restore", { type: "page", id }); return Response.json({ ok: true }); }29  if (action === "duplicate") { const p = await duplicatePage(ws.id, id); await audit(user.id, "page.duplicate", { type: "page", id }, { to: p.id }); return Response.json(p); }30  return Response.json({ error: "Unknown action" }, { status: 400 });31});32
Files · main
Menu

Theme